package Busquedas;

import java.util.ArrayList;
import Problemas.Problema;


/*
 * Clase de la que heredan todas las búsquedas implementadas
 */
public abstract class Busqueda {

	private long tiempoTotal;

	private Nodo nodo;

	private Problema problema;

	private int costeCamino;

	protected ArrayList<Nodo> abiertos;

	protected ArrayList<Estado> expandidos;

	protected ArrayList<String> NombreOper; 

	protected ArrayList<Estado> camino;

	//protected DibujaNodos dibuja ;

	protected int contadorNodos;

	protected int maxContadorNodos=5000;



	/**
	 * Constructor de bússqueda. Inicializa todos los elementos del problema que se quiere resolver.
	 * @param p Problema que queremos resolver con la búsqueda.
	 */
	public Busqueda(Problema p){
		problema = p;
		int numMaxHijos = problema.getnumOper();
		nodo = new Nodo(problema.getInicial(),numMaxHijos,0);
		nodo.setCosteAcumulado(0);
		nodo.setNumOperador(0);
		abiertos = new ArrayList<Nodo>();
		expandidos = new ArrayList<Estado>();
		camino = new ArrayList<Estado>();
		NombreOper=new ArrayList<String>();
		contadorNodos=0;
	}
	
	
	/**
	 * Getter del problema a resolver.
	 * @return problema a resolver.
	 */
	public Problema getProblema() {
		return problema;
	}

	
	/**
	 * Setter del problema a resolver.
	 * @param problema problema que queremos que resuelva la búsqueda.
	 */
	public void setProblema(Problema problema) {
		this.problema = problema;
	}
	
	
	/**
	 * Getter del nodo.
	 * @return nodo visitado.
	 */
	public Nodo getNodo() {
		return nodo;
	}
	
	
	/**
	 * Setter del nodo visitado.
	 * @param nodo Nodo que queremos visitar.
	 */
	public void setNodo(Nodo nodo) {
		this.nodo = nodo;
	}
	
	
	/**
	 * Getter del tiempo de búsqueda.
	 * @return tiempo de búsqueda en milisegundos.
	 */
	public long getTiempoTotal() {
		return tiempoTotal;
	}
	
	
	/**
	 * Setter del tiempo de busqueda.
	 * @param tiempo_total tiempo que tarda la búsqueda.
	 */
	public void setTiempoTotal(long tiempo_total) {
		this.tiempoTotal = tiempo_total;
	}
	
	
	/**
	 * Getter de la lista de estados expandidos.
	 * @return lista de estados expandidos.
	 */
	public ArrayList<Estado> getExpandidos() {
		return expandidos;
	}
	
	
	/**
	 * Setter de estados expandidos.
	 * @param expandidos lista de expandidos que queremos asignar.
	 */
	public void setExpandidos(ArrayList<Estado> expandidos) {
		this.expandidos = expandidos;
	}
	
	
	/**
	 * Getter de la lista con los nombres de operadores.
	 * @return Lista de nombres de operadores.
	 */
	public ArrayList<String> getNombreOper() {
		return NombreOper;
	}
	
	
	/**
	 * Setter de los nombres de los operadores.
	 * @param NombreOper lista con los nombres que queremos asignar.
	 */
	public void setNombreOper(ArrayList<String> NombreOper) {
		this.NombreOper = NombreOper;
	}
	
	
	/**
	 * Getter de camino.
	 * @return lista de estados hasta la soluci�n.
	 */
	public ArrayList<Estado> getCamino() {
		return camino;
	}
	
	
	/**
	 * Setter del camino
	 * @param camino Lista con los estados que forman el camino a la soluci�n.
	 */
	public void setCamino(ArrayList<Estado> camino) {
		this.camino = camino;
	}
	
	
	/**
	 * Getter del coste del camino.
	 * @return entero con el coste del camino.
	 */
	public int getCosteCamino() {
		return costeCamino;
	}
	
	
	/**
	 * Setter del coste del camino.
	 * @param costeCamino entero con el coste a asignar.
	 */
	public void setCosteCamino(int costeCamino) {
		this.costeCamino = costeCamino;
	}
	
	

	
	/**
	 * Método abstracto que realiza la búsqueda del problema. Este método se implementa en cada tipo de búsqueda.
	 * @param controlCiclos booleano para saber si se realiza control de ciclos o no en la búsqueda.
	 * @return Lista de estados con el camino a la soluci�n.
	 */
	public abstract ArrayList<Estado> buscar(boolean controlCiclos);

	
	/**
	 * Método para saber si un estado se encuentra en expandidos.
	 * @param e estado del que buscamos la informaci�n.
	 * @return booleano que comunica si el nodo est� o no en expandidos.
	 */
	protected boolean estaEnExpandidos(Estado e){
		boolean encontrado=false;
		int i=0;
		while (!encontrado && (i<expandidos.size())){
			if (e.esIgual(expandidos.get(i))){
				encontrado=true;
			}
			else i++;
		}
		return encontrado;
	}
	

	/**
	 * Método que genera el camino a la soluci�n. Visita los padres de los nodos desde el final al inicial.
	 * @param n Nodo desde el cual se comienza a generar el camino.
	 */
	public void generaCamino(Nodo n){
		this.setCosteCamino(n.getCosteAcumulado());
		while(n != null){
			camino.add(0,n.getEstado());
			NombreOper.add(0,this.getProblema().getNombreOperador(n.getNumOperador()));//inicial=0
			n = n.getPadre();
		}
		NombreOper.remove(0);
	}
	

}
